package com.geovis.emergency.spd.biz.pc.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geovis.emergency.spd.biz.pc.mapper.PcDisasterEventMapper;
import com.geovis.emergency.spd.biz.pc.mapper.PcDisasterMapper;
import com.geovis.emergency.spd.biz.pc.mapper.PcDrillDisasterEventMapper;
import com.geovis.emergency.spd.biz.pc.service.IPcDisasterEventService;
import com.geovis.emergency.spd.biz.system.service.ISystemFileBusinessService;
import com.geovis.emergency.spd.biz.system.service.ISystemFileService;
import com.geovis.emergency.spd.cache.DictCache;
import com.geovis.emergency.spd.entity.pc.entity.PcDisaster;
import com.geovis.emergency.spd.entity.pc.entity.PcDisasterEvent;
import com.geovis.emergency.spd.entity.pc.entity.PcDrillDisasterEvent;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcDisasterConstant;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDisasterEventSaveDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDisasterEventUpdateDTO;
import com.geovis.emergency.spd.entity.pc.pojo.enums.SourceTypeEnum;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcDisasterEventVO;
import com.geovis.emergency.spd.entity.system.constant.SystemFileBusinessConstant;
import com.geovis.emergency.spd.entity.system.entity.SystemFile;
import com.geovis.emergency.spd.entity.system.entity.SystemFileBusiness;
import com.geovis.emergency.spd.entity.system.pojo.dto.SystemFileDTO;
import com.geovis.emergency.spd.entity.system.pojo.dto.SystemFileQueryDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 应急预案指挥模块-灾害事件管理 服务实现类
 * </p>
 *
 * @author Lonsho
 * @since 2022-06-08
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PcDisasterEventServiceImpl extends ServiceImpl<PcDisasterEventMapper, PcDisasterEvent> implements IPcDisasterEventService {
    private final ISystemFileBusinessService systemFileBusinessService;

    private final PcDisasterMapper pcDisasterMapper;
    private final ISystemFileService systemFileService;

    private final PcDrillDisasterEventMapper pcDrillDisasterEventMapper;;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePcDisasterEvent(PcDisasterEventSaveDTO saveDTO) {
        PcDisasterEvent pcDisasterEvent =  new PcDisasterEvent();

        BeanUtil.copyProperties(saveDTO,pcDisasterEvent);

        String pcDisasterId = pcDisasterEvent.getPcDisasterId();
        PcDisaster pcDisaster = pcDisasterMapper.selectById(pcDisasterId);
        if (ObjectUtil.isNotNull(pcDisaster)){
            pcDisasterEvent.setPcPlanId(pcDisaster.getPcPlanId());
        }
        baseMapper.insert(pcDisasterEvent);
        if (ObjectUtil.isNotEmpty(saveDTO.getFileList())){
            Set<SystemFileBusiness> fileBusinessSet = CollUtil.set(false);
            //关联业务附件
            saveDTO.getFileList().forEach(systemFile ->
                    fileBusinessSet.add(new SystemFileBusiness(systemFile.getId(), SystemFileBusinessConstant.TYPE_PC_DISASTER_EVENT, pcDisasterEvent.getId())));
            systemFileBusinessService.saveBatch(fileBusinessSet);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePcDisasterEvent(PcDisasterEventUpdateDTO updateDTO) {

        PcDisasterEvent pcDisasterEvent =  new PcDisasterEvent();
        BeanUtil.copyProperties(updateDTO,pcDisasterEvent);

        baseMapper.updateById(pcDisasterEvent);
        if (ObjectUtil.isNotEmpty(updateDTO.getFileList())){

            List<String> fileIdList = updateDTO.getFileList().stream().map(SystemFile::getId).collect(Collectors.toList());
            //将已经前端已经删除的文件删除掉
            LambdaQueryWrapper<SystemFileBusiness> updateWrapper = Wrappers.<SystemFileBusiness>lambdaQuery()
                    .eq(SystemFileBusiness::getRelatedId, pcDisasterEvent.getId())
                    .eq(SystemFileBusiness::getType, SystemFileBusinessConstant.TYPE_PC_DISASTER_EVENT)
                    .notIn(SystemFileBusiness::getFileId, fileIdList);
            systemFileBusinessService.remove(updateWrapper);

            Set<SystemFileBusiness> fileBusinessSet = CollUtil.set(false);
            //关联业务附件
            updateDTO.getFileList().forEach(systemFile -> {

               if (systemFileBusinessService.count(Wrappers.<SystemFileBusiness>lambdaQuery()
                        .eq(SystemFileBusiness::getFileId,systemFile.getId())
                        .eq(SystemFileBusiness::getRelatedId, pcDisasterEvent.getId())
                        .eq(SystemFileBusiness::getType, SystemFileBusinessConstant.TYPE_PC_DISASTER_EVENT)) == 0){
                   fileBusinessSet.add(new SystemFileBusiness(systemFile.getId(), SystemFileBusinessConstant.TYPE_PC_DISASTER_EVENT, pcDisasterEvent.getId()));
               }
            });
            systemFileBusinessService.saveBatch(fileBusinessSet);
        }

    }

    @Override
    public List<PcDisasterEventVO> getList(String disasterId) {
        LambdaQueryWrapper<PcDisasterEvent> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(PcDisasterEvent::getPcDisasterId, disasterId);
        wrapper.orderByDesc(PcDisasterEvent::getSubmitTime);
        List<PcDisasterEvent> pcDisasterEvents = baseMapper.selectList(wrapper);
        PcDisaster pcDisaster = pcDisasterMapper.selectById(disasterId);
        return pcDisasterEvents.stream().map(pcDisasterEvent -> {
            PcDisasterEventVO pcDisasterEventVO = new PcDisasterEventVO();
            BeanUtil.copyProperties(pcDisasterEvent, pcDisasterEventVO);
            if (ObjectUtil.isNotNull(pcDisaster)){
                pcDisasterEventVO.setEventType(pcDisaster.getEventType());
            }
            //设置type，level的名称
            if (StrUtil.isNotBlank(pcDisasterEventVO.getType())){
                String disasterType = DictCache.getDictValue(PcDisasterConstant.DISASTER_TYPE, pcDisasterEventVO.getType());
                if (StrUtil.isNotBlank(disasterType)){
                    pcDisasterEventVO.setTypeName(disasterType);
                }
            }
            if (StrUtil.isNotBlank(pcDisasterEventVO.getLevel())){
                String eventLevel = DictCache.getDictValue(PcDisasterConstant.EVENT_LEVEL, pcDisasterEventVO.getLevel());
                if (StrUtil.isNotBlank(eventLevel)){
                    pcDisasterEventVO.setLevelName(eventLevel);
                }
            }
            if(StringUtils.hasText(pcDisaster.getTyphoonNo()))
            {
                pcDisasterEventVO.setTyphoonNo(pcDisaster.getTyphoonNo());
            }
            //附件信息
            List<SystemFile> fileList = systemFileService.getListById(pcDisasterEvent.getId(),SystemFileBusinessConstant.TYPE_PC_DISASTER_EVENT);
            pcDisasterEventVO.setFileList(fileList);
            return pcDisasterEventVO;
        }).collect(Collectors.toList());
    }

    @Override
    public PcDisasterEventVO getDetail(String id) {
        LambdaUpdateWrapper<PcDisasterEvent> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(PcDisasterEvent::getId, id);
        PcDisasterEvent pcDisasterEvent = baseMapper.selectOne(wrapper);
        Assert.notNull(pcDisasterEvent, "灾害事件【{}】不存在",id);

        PcDisasterEventVO pcDisasterEventVO = new PcDisasterEventVO();
        BeanUtil.copyProperties(pcDisasterEvent,pcDisasterEventVO);

        if (StrUtil.isNotBlank(pcDisasterEvent.getType())){
            String dictValue = DictCache.getDictValue(PcDisasterConstant.DISASTER_TYPE, pcDisasterEvent.getType());
            pcDisasterEventVO.setTypeName(dictValue);
        }
        if (StrUtil.isNotBlank(pcDisasterEvent.getLevel())){
            String dictValue = DictCache.getDictValue(PcDisasterConstant.EVENT_LEVEL, pcDisasterEvent.getLevel());
            pcDisasterEventVO.setLevelName(dictValue);
        }
        //附件信息
        List<SystemFile> fileList = systemFileService.getListById(pcDisasterEvent.getId(),SystemFileBusinessConstant.TYPE_PC_DISASTER_EVENT);
        fileList.sort(Comparator.comparing(SystemFile::getCreateTime));
        pcDisasterEventVO.setFileList(fileList);
        return pcDisasterEventVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cleanAll(String disasterId) {
        baseMapper.delete(Wrappers.<PcDisasterEvent>lambdaQuery().eq(PcDisasterEvent::getPcDisasterId,disasterId));
    }

    @Override
    public List<PcDisasterEvent> listAll(String pcDrillId) {
        // 过滤掉当前演练已经配置的事件
        List<String> pcDrillDisasterEvents = pcDrillDisasterEventMapper.selectList(
                Wrappers.<PcDrillDisasterEvent>lambdaQuery()
                        .select(PcDrillDisasterEvent::getPcDisasterEventId)
                        .isNotNull(PcDrillDisasterEvent::getPcDrillDisasterId)
                        .eq(PcDrillDisasterEvent::getSourceType, SourceTypeEnum.REPOSITORY.getCode())
                        .eq(PcDrillDisasterEvent::getPcDrillId, pcDrillId)
        ).stream().map(PcDrillDisasterEvent::getPcDisasterEventId).collect(Collectors.toList());
        return baseMapper.selectList(
                Wrappers.<PcDisasterEvent>lambdaQuery()
                        .notIn(CollUtil.isNotEmpty(pcDrillDisasterEvents),PcDisasterEvent::getId,pcDrillDisasterEvents)
                        .last("limit 100")
        );
    }
}
